using System;
using System.Linq;
using MbUnit.Framework;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace Sapphire.Linq.Tests
{
    public class QueriesTests : DataContextBaseTests
    {
        protected SPQuery LastQuery
        {
            get
            {
                Assert.Count(1, LastQueries);
                return LastQueries.First();
            }
        }

        [Test]
        void get_all_tasks_from_list()
        {
            DataContext.Tasks.ToList();

            Assert.AreEqual(string.Empty, LastQuery.Query);
        }

        [Test]
        void get_first_task()
        {
            DataContext.Tasks.First();

            Assert.AreEqual(string.Empty, LastQuery.Query);
            Assert.AreEqual<uint>(1, LastQuery.RowLimit);
        }

        [Test]
        void get_empty_task_with_id_more_than_10()
        {
            DataContext.Tasks.First(x => x.ID > 10);

            const string expectedQuery = @"<Where>
  <Gt>
    <FieldRef ID=""1d22ea11-1e32-424e-89ab-9fedbadb6ce1"" />
    <Value Type=""Number"">10</Value>
  </Gt>
</Where>";
            Assert.AreEqual(expectedQuery, LastQuery.Query);
            Assert.AreEqual<uint>(1, LastQuery.RowLimit);
        }

        [Test]
        void get_tasks_for_today()
        {
            var today = DateTime.Now;
            DataContext.Tasks
                .Where(x => x.StartDate > today &&
                    x.StartDate < today.AddDays(1))
                .ToList();

            string expectedQuery = string.Format(@"<Where>
  <And>
    <Lt>
      <FieldRef Name=""StartDate"" />
      <Value Type=""Text"">{1}</Value>
    </Lt>
    <Gt>
      <FieldRef Name=""StartDate"" />
      <Value Type=""Text"">{0}</Value>
    </Gt>
  </And>
</Where>",
SPUtility.CreateISO8601DateTimeFromSystemDateTime(today),
SPUtility.CreateISO8601DateTimeFromSystemDateTime(today.AddDays(1)));

            Assert.AreEqual(expectedQuery, LastQuery.Query);
        }

        [Test]
        void get_tasks_with_Hello_in_title()
        {
            DataContext.Tasks
                .Where(x => x.Title123.Contains("Hello"))
                .ToList();

            string expectedQuery = @"<Where>
  <Contains>
    <FieldRef Name=""Title"" />
    <Value Type=""Text"">Hello</Value>
  </Contains>
</Where>";

            Assert.AreEqual(expectedQuery, LastQuery.Query);
        }

        [Test]
        void get_tasks_starts_with_Hello_in_title()
        {
            DataContext.Tasks
                .Where(x => x.Title123.StartsWith("Hello"))
                .ToList();

            string expectedQuery = @"<Where>
  <BeginsWith>
    <FieldRef Name=""Title"" />
    <Value Type=""Text"">Hello</Value>
  </BeginsWith>
</Where>";

            Assert.AreEqual(expectedQuery, LastQuery.Query);
        }

        [Test]
        void get_tasks_with_id_not_equal_to_one()
        {
            DataContext.Tasks.Where(x => x.ID != 1).ToList();

            string expectedQuery = @"<Where>
  <Neq>
    <FieldRef ID=""1d22ea11-1e32-424e-89ab-9fedbadb6ce1"" />
    <Value Type=""Number"">1</Value>
  </Neq>
</Where>";

            Assert.AreEqual(expectedQuery, LastQuery.Query);
        }

        [Test]
        void get_tasks_with_not_null_assignment()
        {
            DataContext.Tasks.Where(x => x.AssignedTo != null).ToList();

            string expectedQuery = @"<Where>
  <IsNotNull>
    <FieldRef Name=""AssignedTo"" />
  </IsNotNull>
</Where>";

            Assert.AreEqual(expectedQuery, LastQuery.Query);
        }

        [Test]
        void get_tasks_paged()
        {
            DataContext.Tasks.Skip(20).Take(10).ToList();

            Assert.AreEqual(2, LastQueries.Count, "paging should be realized by two queries and calling SPListItemCollectionPosition of first results");
            Assert.AreEqual<uint>(20, LastQueries[0].RowLimit);
            Assert.AreEqual<uint>(10, LastQueries[1].RowLimit);
        }

        [Test]
        void get_tasks_ordered_by_start_date_asc()
        {
            DataContext.Tasks.OrderBy(x => x.StartDate).ToList();

            string expectedQuery = @"<OrderBy>
  <FieldRef Name=""StartDate"" />
</OrderBy>";

            Assert.AreEqual(expectedQuery, LastQuery.Query);
        }

        [Test]
        void get_tasks_ordered_by_start_date_desc()
        {
            DataContext.Tasks.OrderByDescending(x => x.StartDate).ToList();

            string expectedQuery = @"<OrderBy>
  <FieldRef Name=""StartDate"" Ascending=""DESC"" />
</OrderBy>";

            Assert.AreEqual(expectedQuery, LastQuery.Query);
        }

        [Test]
        void get_tasks_count()
        {
            DataContext.Tasks.Count();

            Assert.AreEqual(0, LastQueries.Count, "Count() must be called SPList.ItemsCount directly");
        }
    }
}